package com.example.guesswho.ui.viewmodel

import android.app.Application
import android.content.Context
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import com.example.guesswho.ParseClient
import com.example.guesswho.data.parse.AudienceChat
import com.example.guesswho.data.parse.Room
import com.parse.ParseCloud
import com.parse.ParseLiveQueryClient
import com.parse.ParseObject
import com.parse.ParseQuery
import com.parse.ParseUser
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import kotlinx.coroutines.tasks.await
import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.common.MediaItem
import androidx.media3.common.Player

class GameViewModel(application: Application) : AndroidViewModel(application) {
    
    // Game state
    private val _timeLeft = MutableStateFlow(60)
    val timeLeft: StateFlow<Int> = _timeLeft.asStateFlow()
    
    private val _clueIndex = MutableStateFlow(0)
    val clueIndex: StateFlow<Int> = _clueIndex.asStateFlow()
    
    private val _score = MutableStateFlow(0)
    val score: StateFlow<Int> = _score.asStateFlow()
    
    private val _unansweredCount = MutableStateFlow(0)
    val unansweredCount: StateFlow<Int> = _unansweredCount.asStateFlow()
    
    private val _isGameActive = MutableStateFlow(false)
    val isGameActive: StateFlow<Boolean> = _isGameActive.asStateFlow()
    
    // Room data
    private val _currentRoom = MutableStateFlow<Room?>(null)
    val currentRoom: StateFlow<Room?> = _currentRoom.asStateFlow()
    
    // Danmaku messages
    private val _danmakuMessages = MutableStateFlow<List<AudienceChat>>(emptyList())
    val danmakuMessages: StateFlow<List<AudienceChat>> = _danmakuMessages.asStateFlow()
    
    // Player info
    private val _currentUsername = MutableStateFlow("")
    val currentUsername: StateFlow<String> = _currentUsername.asStateFlow()
    
    // ExoPlayer for sound effects
    private var exoPlayer: ExoPlayer? = null
    private val liveQueryClient: ParseLiveQueryClient = ParseLiveQueryClient.Factory.getClient()
    private var roomSubscription: ParseLiveQueryClient.Subscription? = null
    
    init {
        initializePlayer()
        initializeUser()
    }
    
    private fun initializePlayer() {
        val context = getApplication<Application>().applicationContext
        exoPlayer = ExoPlayer.Builder(context).build().apply {
            repeatMode = Player.REPEAT_MODE_OFF
        }
    }
    
    private fun initializeUser() {
        val currentUser = ParseUser.getCurrentUser()
        _currentUsername.value = currentUser?.username ?: "匿名玩家"
    }
    
    fun startGame(roomId: String) {
        viewModelScope.launch {
            _isGameActive.value = true
            _timeLeft.value = 60
            _score.value = 0
            _clueIndex.value = 0
            
            // Fetch room data
            fetchRoomData(roomId)
            
            // Subscribe to live updates
            subscribeToRoomUpdates(roomId)
            
            // Start game timer
            startGameTimer()
        }
    }
    
    private fun fetchRoomData(roomId: String) {
        viewModelScope.launch {
            try {
                val query = ParseQuery.getQuery<ParseObject>("Room")
                query.whereEqualTo("objectId", roomId)
                val roomObject = query.first.await()
                val room = Room.fromParseObject(roomObject)
                _currentRoom.value = room
                _unansweredCount.value = room.unansweredCount
            } catch (e: Exception) {
                // Handle error
            }
        }
    }
    
    private fun subscribeToRoomUpdates(roomId: String) {
        viewModelScope.launch {
            try {
                val query = ParseQuery.getQuery<ParseObject>("Room")
                query.whereEqualTo("objectId", roomId)
                
                roomSubscription = liveQueryClient.subscribe(query)
                
                roomSubscription?.handleSubscribe {
                    // Successfully subscribed
                }
                
                roomSubscription?.handleEvent(ParseLiveQueryClient.EVENT_UPDATE) { query, roomObject ->
                    roomObject?.let { room ->
                        val updatedRoom = Room.fromParseObject(room)
                        _currentRoom.value = updatedRoom
                        _unansweredCount.value = updatedRoom.unansweredCount
                        
                        // Update score based on room data or user's score in the room
                        updateScoreFromRoom(updatedRoom)
                    }
                }
                
                // Also subscribe to audience chat for this room
                subscribeToChatUpdates(roomId)
                
            } catch (e: Exception) {
                // Handle subscription error
            }
        }
    }
    
    private fun subscribeToChatUpdates(roomId: String) {
        viewModelScope.launch {
            try {
                val chatQuery = ParseQuery.getQuery<ParseObject>("AudienceChat")
                chatQuery.whereEqualTo("roomId", roomId)
                chatQuery.orderByDescending("createdAt")
                chatQuery.limit = 50
                
                val chatSubscription = liveQueryClient.subscribe(chatQuery)
                
                chatSubscription.handleEvent(ParseLiveQueryClient.EVENT_CREATE) { query, chatObject ->
                    chatObject?.let { chat ->
                        val newChat = AudienceChat.fromParseObject(chat)
                        _danmakuMessages.value = listOf(newChat) + _danmakuMessages.value.take(49)
                    }
                }
                
            } catch (e: Exception) {
                // Handle chat subscription error
            }
        }
    }
    
    private fun updateScoreFromRoom(room: Room) {
        // This would typically get the current user's score from the room
        // For now, we'll simulate it based on unanswered count
        val newScore = maxOf(0, 1000 - (room.unansweredCount * 50))
        _score.value = newScore
    }
    
    private fun startGameTimer() {
        viewModelScope.launch {
            while (_isGameActive.value && _timeLeft.value > 0) {
                kotlinx.coroutines.delay(1000)
                _timeLeft.value--
                
                if (_timeLeft.value == 0) {
                    endGame()
                }
            }
        }
    }
    
    fun nextClue() {
        if (_clueIndex.value < 4) { // Assuming max 5 clues (0-4)
            _clueIndex.value++
        }
    }
    
    fun previousClue() {
        if (_clueIndex.value > 0) {
            _clueIndex.value--
        }
    }
    
    fun answer(optionIndex: Int, roomId: String, questionId: String) {
        viewModelScope.launch {
            try {
                // Call Parse Cloud Code function
                val params = mapOf(
                    "roomId" to roomId,
                    "questionId" to questionId,
                    "optionIndex" to optionIndex,
                    "username" to _currentUsername.value
                )
                
                val result = ParseCloud.callFunction<>("answerQuestion", params).await()
                
                // Check if answer was correct
                val isCorrect = result["isCorrect"] as? Boolean ?: false
                val pointsEarned = result["pointsEarned"] as? Int ?: 0
                
                if (isCorrect) {
                    // Update score
                    _score.value += pointsEarned
                    
                    // Play success sound
                    playSuccessSound()
                    
                    // Post success danmaku
                    postDanmaku(roomId, "答对了！+${pointsEarned}分")
                } else {
                    // Play failure sound
                    playFailureSound()
                    
                    // Post failure danmaku
                    postDanmaku(roomId, "答错了，再接再厉！")
                }
                
                // Move to next clue or next question
                if (_clueIndex.value < 4) {
                    nextClue()
                }
                
            } catch (e: Exception) {
                // Handle answer submission error
                postDanmaku(roomId, "提交答案失败，请重试")
            }
        }
    }
    
    fun postDanmaku(roomId: String, text: String) {
        viewModelScope.launch {
            try {
                val chat = AudienceChat(
                    objectId = "",
                    roomId = roomId,
                    username = _currentUsername.value,
                    text = text,
                    ts = System.currentTimeMillis()
                )
                
                val chatObject = chat.toParseObject()
                chatObject.saveInBackground { exception ->
                    if (exception != null) {
                        // Handle save error
                    }
                }
                
            } catch (e: Exception) {
                // Handle danmaku posting error
            }
        }
    }
    
    private fun playSuccessSound() {
        try {
            val context = getApplication<Application>().applicationContext
            val mediaItem = MediaItem.fromUri("android.resource://${context.packageName}/raw/success_sound")
            exoPlayer?.setMediaItem(mediaItem)
            exoPlayer?.prepare()
            exoPlayer?.play()
        } catch (e: Exception) {
            // Handle sound playback error
        }
    }
    
    private fun playFailureSound() {
        try {
            val context = getApplication<Application>().applicationContext
            val mediaItem = MediaItem.fromUri("android.resource://${context.packageName}/raw/failure_sound")
            exoPlayer?.setMediaItem(mediaItem)
            exoPlayer?.prepare()
            exoPlayer?.play()
        } catch (e: Exception) {
            // Handle sound playback error
        }
    }
    
    fun endGame() {
        viewModelScope.launch {
            _isGameActive.value = false
            
            // Unsubscribe from live queries
            roomSubscription?.unsubscribe()
            
            // Post game over danmaku
            _currentRoom.value?.let { room ->
                postDanmaku(room.objectId, "游戏结束！最终得分: ${_score.value}")
            }
            
            // Release player resources
            exoPlayer?.release()
            exoPlayer = null
        }
    }
    
    fun resetGame() {
        _timeLeft.value = 60
        _score.value = 0
        _clueIndex.value = 0
        _unansweredCount.value = 0
        _isGameActive.value = false
        _currentRoom.value = null
        _danmakuMessages.value = emptyList()
        
        // Re-initialize player for next game
        initializePlayer()
    }
    
    override fun onCleared() {
        super.onCleared()
        
        // Clean up resources
        roomSubscription?.unsubscribe()
        exoPlayer?.release()
    }
}